package com.frejoys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.frejoys.common.dto.admin.StoreIdAndNameDto;
import com.frejoys.common.dto.app.StoreWalletLogPageDto;
import com.frejoys.common.dto.common.IdDto;
import com.frejoys.common.dto.store.StoreCashDto;
import com.frejoys.common.dto.store.StoreCashListDto;
import com.frejoys.common.dto.store.StoreIdAndPageDto;
import com.frejoys.common.enums.*;
import com.frejoys.common.error.HttpStatus;
import com.frejoys.common.exception.GeneralException;
import com.frejoys.common.util.AppConfigUtil;
import com.frejoys.common.util.SnowflakeUtil;
import com.frejoys.common.util.TimeUtil;
import com.frejoys.common.vo.admin.StoreWalletListVo;
import com.frejoys.common.vo.app.StoreWalletLogListVo;
import com.frejoys.common.vo.app.StoreWalletLogPageVo;
import com.frejoys.common.vo.store.StoreCashListVo;
import com.frejoys.common.vo.store.StoreUserVo;
import com.frejoys.dao.entity.*;
import com.frejoys.dao.mapper.StoreMapper;
import com.frejoys.dao.mapper.StoreUserMapper;
import com.frejoys.dao.mapper.StoreWalletLogMapper;
import com.frejoys.dao.mapper.UserCashMapper;
import com.frejoys.service.PlatformService;
import com.frejoys.service.StoreWalletLogService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class StoreWalletLogServiceImpl extends ServiceImpl<StoreWalletLogMapper, StoreWalletLog> implements StoreWalletLogService {

    private final StoreMapper storeMapper;

    private final StoreUserMapper storeUserMapper;

    private final PlatformService platformService;

    private final UserCashMapper userCashMapper;

    @Override
    public boolean addInfo(Integer storeId, BigDecimal money, BigDecimal cashMoney, BigDecimal cashCharges, Long drawSn, Integer type, Integer createTime, Integer status) {
        return save(new StoreWalletLog() {{
            setStoreId(storeId);
            setMoney(money);
            setCashMoney(cashMoney);
            setCashCharges(cashCharges);
            setDrawSn(drawSn);
            setType(type);
            setCreateTime(createTime);
            setUpdateTime(createTime);
            setStatus(status);
        }});
    }

    /**
     * 获取店铺钱包记录
     *
     * @param dto
     * @param userId
     * @return
     */
//    @Override
//    public List<StoreWalletLogListVo> storeWalletListInfo(StoreIdAndPageDto dto) {
//        Page page = new Page<>(dto.getPage(), dto.getSize());
//        page.setSearchCount(false);
//
//        LambdaQueryWrapper<Store> queryWrapper = new LambdaQueryWrapper<>();
//        queryWrapper.select(Store::getName)
//                .eq(Store::getId, dto.getId());
//        Store store = storeMapper.selectOne(queryWrapper);
//
//        LambdaQueryWrapper<StoreWalletLog> wrapper = new LambdaQueryWrapper<>();
//        wrapper.select(StoreWalletLog::getId, StoreWalletLog::getStoreId, StoreWalletLog::getMoney, StoreWalletLog::getDrawSn, StoreWalletLog::getType, StoreWalletLog::getStatus);
//        wrapper.eq(StoreWalletLog::getStoreId, dto.getId());
//        wrapper.orderByDesc(StoreWalletLog::getCreateTime);
//
//        List<StoreWalletLog> storeWalletLogs = baseMapper.selectList(page, wrapper);
//        List<StoreWalletLogListVo> list = new ArrayList<>();
//
//        if (!storeWalletLogs.isEmpty()) {
//
//            storeWalletLogs.forEach(storeWalletLog -> {
//                StoreWalletLogListVo vo = new StoreWalletLogListVo();
//                vo.setId(storeWalletLog.getId());
//                vo.setStoreId(storeWalletLog.getStoreId());
//                vo.setType(storeWalletLog.getType());
//                vo.setMoney(storeWalletLog.getMoney());
//                vo.setMoney(storeWalletLog.getMoney());
//                vo.setDrawSn(storeWalletLog.getDrawSn());
//                vo.setStatus(storeWalletLog.getStatus());
//                vo.setStoreName(store.getName());
//                list.add(vo);
//            });
//        }
//        return list;
//    }

    @Override
    public Page<StoreWalletLogPageVo> walletLogPage(StoreWalletLogPageDto dto) {

        Page<StoreWalletLogPageVo> page = new Page<>(dto.getPage(), dto.getSize());
        Page<StoreWalletLogPageVo> walletLogPageVos = baseMapper.selectPageWalletLog(page, dto);
        List<StoreWalletLogPageVo> list = walletLogPageVos.getRecords();

        if (CollectionUtil.isNotEmpty(list)) {
            //获取店铺的拥有者
            List<Integer> storeIds = list.stream().map(StoreWalletLogPageVo::getStoreId).toList();

            //根据店铺获取店铺拥有者
            List<StoreUserVo> storeUserByStoreIds = storeUserMapper.getStoreUserByStoreIds(storeIds);
            List<Long> ids = storeUserByStoreIds.stream().map(StoreUserVo::getUserId).toList();

            //店铺id ，用户id
            Map<Integer, Long> map = storeUserByStoreIds.stream().collect(Collectors.toMap(StoreUserVo::getStoreId, StoreUserVo::getUserId));

            //店铺id 用户手机号
            Map<Integer, String> stringMap = storeUserByStoreIds.stream().collect(Collectors.toMap(StoreUserVo::getStoreId, StoreUserVo::getPhone));
            List<UserCash> userCashes;

            Map<Long, UserCash> userCashMap = new HashMap<>();
            if (dto.getType() != null && dto.getType().equals(EStoreWalletLogType.cash.getValue())) {
                LambdaQueryWrapper<UserCash> wrapper = Wrappers.lambdaQuery();
                wrapper.select(UserCash::getAccount, UserCash::getUsername, UserCash::getWxImg, UserCash::getType, UserCash::getUserId)
                        .in(UserCash::getUserId,ids);
                userCashes = userCashMapper.selectList(wrapper);
                if(CollectionUtil.isNotEmpty(userCashes)) {
                    userCashMap = userCashes.stream().collect(Collectors.toMap(UserCash::getUserId, u -> u));
                }
            }

            for (StoreWalletLogPageVo s : list) {

                s.setLogoUrl(AppConfigUtil.getUrlPrefix(s.getLogo(), EFileSize.logo.getValue()));
                s.setCoverUrl(AppConfigUtil.getUrlPrefix(s.getCover()));
                s.setPhone(stringMap.get(s.getStoreId()));

                UserCash userCash = userCashMap.get(map.get(s.getStoreId()));

                if (ObjectUtil.isNotEmpty(userCash)){
                    s.setWxImg(AppConfigUtil.getUrlPrefix(ObjectUtil.isEmpty(userCash) ? "" : userCash.getWxImg()));
                    s.setUsername(userCash.getUsername());
                    s.setAccount(userCash.getAccount());
                    s.setCashType(userCash.getType());

                }
            }
        }
        return walletLogPageVos;
    }

    @Override
    public boolean walletCash(Long userId, StoreCashDto dto) {

        // 校验店铺
        Integer suId = storeUserMapper.getIdByStoreRole(userId, dto.getStoreId(), EStoreUserType.owner.getValue());
        if (suId == null) {
            throw new GeneralException(HttpStatus.storeUserCashError);
        }

        Platform platform = platformService.getInfo();

        return save(new StoreWalletLog() {{
            setStoreId(dto.getStoreId());
            // 负数
            setMoney(dto.getMoney().negate());
            setCashMoney(dto.getMoney());
            setCashCharges(BigDecimal.ZERO);
            setDrawSn(SnowflakeUtil.appNextId());
            setType(EStoreWalletLogType.cash.getValue());
            setCreateTime(TimeUtil.unixTime());
            setUpdateTime(TimeUtil.unixTime() + platform.getStoreCashTime());
            setStatus(EPayStatus.wait.getValue());
        }});
    }

    @Override
    public boolean checkStoreWalletLog(IdDto dto) {
        LambdaQueryWrapper<StoreWalletLog> wrapper = Wrappers.lambdaQuery();
        wrapper.select(StoreWalletLog::getStoreId, StoreWalletLog::getCashMoney, StoreWalletLog::getType, StoreWalletLog::getStatus).eq(StoreWalletLog::getId, dto.getId());
        StoreWalletLog walletLog = getOnly(wrapper);

        if (!walletLog.getType().equals(EStoreWalletLogType.cash.getValue())) {
            throw new GeneralException(HttpStatus.applyError);
        }

        if (walletLog.getCashMoney().compareTo(BigDecimal.ZERO) == 0 || walletLog.getStatus().equals(EStatus.on.getValue())) {
            throw new GeneralException(HttpStatus.moneyCashExist);
        }

        Store store = storeMapper.getInfo(walletLog.getStoreId());

        if (ObjectUtil.isEmpty(store)) {
            throw new GeneralException(HttpStatus.storeNotFound);
        }

        // 店铺状态异常
        if (store.getStatus() < EStatus.on.getValue()) {
            throw new GeneralException(HttpStatus.storeStatusError);
        }
        // return update(Wrappers.<StoreWalletLog>lambdaUpdate().eq(StoreWalletLog::getId, dto.getId())
        //         .set(StoreWalletLog::getUpdateTime, TimeUtil.unixTime()).set(StoreWalletLog::getStatus, EStatus.on.getValue()));
        return baseMapper.upCashStatus(dto.getId(), walletLog.getCashMoney(), TimeUtil.unixTime(), EPayStatus.wait.getValue(), EPayStatus.finish.getValue());
    }


    //
    @Override
    public List<StoreCashListVo> storeCashListInfo(StoreCashListDto dto) {

        if (dto.getStoreId() == null){
            return new ArrayList<>();
        }

        Page page = new Page<>(dto.getPage(), dto.getSize());
        page.setSearchCount(false);

        LambdaQueryWrapper<StoreWalletLog> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StoreWalletLog::getStoreId,dto.getStoreId());
        if (dto.getType() != null){
            wrapper.eq(StoreWalletLog::getType,dto.getType());
        }
        if (dto.getStatus() != null){
            wrapper.eq(StoreWalletLog::getStatus,dto.getStatus());
        }
        if (StrUtil.isNotEmpty(dto.getTime())){
            //当月开始时间
            int startTime = TimeUtil.beginOfMonth(TimeUtil.unixTime(dto.getTime()));

            //当月结束时间
            int endTime = TimeUtil.endOfMonth(TimeUtil.unixTime(dto.getTime()));

            wrapper.ge(StoreWalletLog::getCreateTime,startTime)
                    .le(StoreWalletLog::getCreateTime,endTime);
        }
        wrapper.orderByDesc(StoreWalletLog::getCreateTime);
        List<StoreWalletLog> storeWalletLogs = baseMapper.selectList(page, wrapper);
        return BeanUtil.copyToList(storeWalletLogs,StoreCashListVo.class);
    }

}
